﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DARE;
using Microsoft.Xna.Framework;

namespace DARE
{
    /// <summary>
    /// It represents a book with every widget you want in it.
    /// This is a MainWindow with a HorizontalSelector in it.
    /// You can use it as an inventory as in the example below with two pages.
    /// </summary>
    /// <example>
    /// <code>
    /// DARE.CInventory inv = new DARE.CInventory(HUD, null, "inventory");
    /// inv.Position = new Vector2(450, 50);
    /// inv.NbItems = 20;
    /// inv.AllowedTypes.Add(2);
    /// inv.AllowedTypes.Add(1);
    /// inv.AllowedTypes.Add(5);
    ///
    /// CBook inventory = new CBook(HUD, "book", new Vector2(250, 200));
    /// inventory.Pages.Add(inv.Clone());
    /// inventory.Pages.Add(inv.Clone());
    /// inventory.Show();
    /// inventory.Position = new Vector2(15, 15);
    /// </code>
    /// </example>
    [AttrTypeDependentSerializable(typeof(CBookData))]
    public class CBook: CWidget
    {
        #region fields

        private CMainWindow m_win;
        private CHorizontalSelector m_pages;
        private bool alreadyActualized = false;

        #endregion

        #region properties

        /// <summary>
        /// If the value is between 0 and 1, the size is a percentage of the size of the parent
        /// (if the parent is null, the value is a percentage of the window).
        /// Else, the value is absolute.
        /// </summary>
        public override Vector2 Size
        {
            get
            {
                return m_win.Size;
            }
            set
            {
                m_win.Size = value;
                m_win.Actualize();
            }
        }

        /// <summary>
        /// If the value is between 0 and 1, the position is a percentage of the size of the parent
        /// (if the parent is null, the value is a percentage of the window).
        /// The value is relative to its parent.
        /// </summary>
        public override Vector2 Position
        {
            get
            {
                return base.Position;
            }
            set
            {
                m_win.Position = value;
                m_win.Actualize();
            }
        }

        /// <summary>
        /// Gets/Sets the rectangle where the widget will be draw.
        /// This value is automatically set when the position and/or the size are set.
        /// If you plan to use a different rectangle than the one automatically created,
        /// we recommand you to use the UseDrawableRect and DrawableRect properties.
        /// </summary>
        /// <seealso cref="UseDrawableRect"/>
        /// <seealso cref="DrawableRect"/>
        public override Rectangle Rect
        {
            get
            {
                return base.Rect;
            }
            set
            {
                m_win.Rect = value;
                m_win.Actualize();
            }
        }

        /// <summary>
        /// Represents the texture of the widget.
        /// For an animated widget, the animation state is contained in this CHUDTexture
        /// </summary>
        public override CHudTexture Texture
        {
            get
            {
                return m_win.Texture;
            }
            set
            {
                if (m_win != null)
                    m_win.Texture = value;
            }
        }

        /// <summary>
        /// Gets/Sets he position of the CHorizontalSelector representing the pages of the book
        /// </summary>
        /// <seealso cref="CHorizontalSelector"/>
        public Vector2 ItemsPosition
        {
            get { return m_pages.Position; }
            set { m_pages.Position = value; }
        }

        /// <summary>
        /// Gets/Sets he size of the CHorizontalSelector representing the pages of the book
        /// </summary>
        /// <seealso cref="CHorizontalSelector"/>
        public Vector2 ItemsSize
        {
            get { return m_pages.Size; }
            set { m_pages.Size = value; }
        }

        /// <summary>
        /// Gets/Sets the CHorizontalSelector representing the pages of the book
        /// </summary>
        /// <seealso cref="CHorizontalSelector"/>
        public CHorizontalSelector Pages { get { return m_pages; } set { m_pages = value; } }

        /// <summary>
        /// set this value to true if you want to display the number of the pages automatically in the book.
        /// </summary>
        /// <seealso cref="NumPageColor"/>
        public bool DisplayNumPage { get { return m_pages.DisplayNumPage; } set { m_pages.DisplayNumPage = value; } }

        /// <summary>
        /// Gets/Sets the color of the 'number of pages' displayed if this one is displayed
        /// </summary>
        /// <seealso cref="DisplayNumPage"/>
        public Color NumPageColor { get { return m_pages.NumPageColor; } set { m_pages.NumPageColor = value; } }

        /// <summary>
        /// Gets/Sets the title of the book displayed on the top CMenuBar.
        /// </summary>
        public string Title { get { return m_win.Title; } set { m_win.Title = value; } }

        #endregion

        #region ctor

        protected void ctor(CHUDSystem hud, string name, Vector2 size)
        {
            if (HUD.Widgets.ContainsKey(name + "_window"))
                m_win = HUD.Widgets[name + "_window"] as CMainWindow;
            else
                m_win = new CMainWindow(HUD, null, name + "_window");
            m_win.Size = size;
            m_parent = m_win;
            IsContainerGroup = true;
            initialize();
            m_isVisible = true;
            m_win.Show();
            if (HUD.Widgets.ContainsKey(name + "_pages"))
                m_pages = HUD.Widgets[name + "_pages"] as CHorizontalSelector;
            else
                m_pages = new CHorizontalSelector(HUD, m_win, name + "_pages");
            m_pages.Size = new Vector2(size.X, size.Y - m_win.Menubar.Rect.Height);
            m_pages.Actualize();
            m_pages.EnableLoop = false;
            m_size = Vector2.Zero;
            m_rect = Rectangle.Empty;
        }

        public CBook(DARE.CHUDSystem hud, CWidget parent, string name)
            : base(hud, parent, name)
        {
            ctor(hud, name, Vector2.One);
        }

        public CBook(CHUDSystem hud, string name, Vector2 size)
            : base(hud, null, name)
        {
            ctor(hud, name, size);

        }

        #endregion

        #region getElements

        /// <summary>
        /// Gets a widget that is under the cursor
        /// </summary>
        public override CWidget GetElement(CMouse mouse, CWidget except)
        {
            if (m_pages != except && m_pages.isMouseOver(mouse))
                return m_pages.GetElement(mouse, except);
            return this;
        }

        public override CWidget GetElement(CMouse mouse)
        {
            return GetElement(mouse, (CWidget)null);
        }

        /// <summary>
        /// Gets a widget that is under the cursor
        /// </summary>
        public override CWidget GetElement(CMouse mouse, Type except)
        {
            if (m_pages.GetType() != except && m_pages.isMouseOver(mouse))
                return m_pages.GetElement(mouse, except);
            return this;
        }

        #endregion

        #region events

        /// <summary>
        /// This attachs a containable widget to a container in a widget that is a container group (`IsContainerGroup = true`)
        /// </summary>
        /// <param name="from">This is the widget to be attached</param>
        /// <param name="to">Can be a cumulable widget to which we want to attach the "from" widget. For example, if you drop a Vignette on another representing the same item, and if this vignette is cumulable, set the give the vignette on which you will attach the first one.</param>
        public override bool Attach(CWidget from, CWidget to)
        {
            return m_pages.Attach(from, to);
        }
        public override bool Attach(CWidget from)
        {
            return Attach(from, null);
        }

        /// <summary>
        /// Method called whenever the mouse is pressed and is over this widget
        /// </summary>
        public override bool onClick(CMouse mouse)
        {
            if (m_pages.isMouseOver(mouse))
                return m_pages.onClick(mouse);
            return true;
        }

        /// <summary>
        /// Method called whenever the mouse is released and is over this widget and was pressed over this widget
        /// </summary>
        public override bool onRelease(CMouse mouse)
        {
            if (m_pages.isMouseOver(mouse))
                return m_pages.onRelease(mouse);
            return true;
        }

        #endregion

        #region methods

        /// <summary>
        /// Actualizes the widget.
        /// If anything has changed, it will allow this widget to get back its parameters.
        /// For example, if the size of the widget is a percentage of the size of its parent,
        /// if the parent's size changes, it will recalculate the good size of this widget.
        /// (This method is called automatically but you can force a new actualization).
        /// </summary>
        public override void Actualize()
        {
            base.Actualize();
        }

        public override bool Update(GameTime m_gameTime)
        {
            if (m_pages != null)
                if (m_pages.Children.Count > 0 && !m_isFixedSize)
                    Size = m_pages.Size + new Vector2(0, (m_win as CMainWindow).Menubar.Rect.Height);
            return base.Update(m_gameTime);
        }

        #endregion
    }
}
